package ali

// 参考文档：https://help.aliyun.com/document_detail/184381.html
import (
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
	"github.com/pkg/errors"
	"go.uber.org/zap"
)

type StsConfig struct {
	RegionId        string `json:"region_id" validate:"required"`         // 操作资源所在的阿里云区域ID，参考：https://help.aliyun.com/document_detail/198107.html?spm=5176.8465980.top-nav.5.4e701450YVM4P2&scm=20140722.S_help%40%40%E6%96%87%E6%A1%A3%40%40198107.S_0%2Bos0.ID_198107-RL_regionId-LOC_consoleUNDhelp-OR_ser-V_2-P0_0
	AccessKeyId     string `json:"access_key_id" validate:"required"`     // RAM 用户或 RAM 角色的 AccessKeyId
	AccessKeySecret string `json:"access_key_secret" validate:"required"` // RAM 用户或 RAM 角色的 AccessKeySecret
	RoleArn         string `json:"role_arn"`                              // 要扮演的 RAM 角色的 ARN
}

type StsHandler struct {
	Client  *sts.Client
	Request *sts.AssumeRoleRequest
	Logger  zap.Logger
}

// BuildHandler 构建 STS 操作助手
func BuildStsHandler(c *StsConfig) (*StsHandler, error) {
	// 构建一个阿里云客户端, 用于发起请求
	client, err := sts.NewClientWithAccessKey(c.RegionId, c.AccessKeyId, c.AccessKeySecret)
	if err != nil {
		return nil, err
	}
	// 构建请求对象
	request := sts.CreateAssumeRoleRequest()
	request.Scheme = "https"
	request.RoleArn = c.RoleArn
	return &StsHandler{Client: client, Request: request}, nil
}

// AssumeRoleOption 参数说明：https://help.aliyun.com/document_detail/371864.html
type AssumeRoleOption struct {
	DurationSeconds int    // Token有效期，单位：秒。token 有效期最小值为 900 秒，最大值为要扮演角色的 MaxSessionDuration 时间。默认值为3600秒。
	Policy          string // 为 STS Token 额外添加的一个权限策略，进一步限制 STS Token 的权限。
	RoleArn         string // 要扮演的 RAM 角色的 ARN
}

// GetCert 获取 STS 证书
func (h *StsHandler) GetCert(sessName string, opt *AssumeRoleOption) (*sts.AssumeRoleResponse, error) {
	// 1. 设置请求信息
	h.Request.RoleSessionName = sessName
	if opt != nil {
		if opt.Policy != "" {
			h.Request.Policy = opt.Policy
		}
		if opt.RoleArn != "" {
			h.Request.RoleArn = opt.RoleArn
		}
		if opt.DurationSeconds != 0 {
			h.Request.DurationSeconds = requests.NewInteger(opt.DurationSeconds)
		}
	}
	// 2. 发起请求，接收和判断响应结果
	res, err := h.Client.AssumeRole(h.Request)
	if err != nil {
		return nil, errors.Cause(err)
	}
	if !res.IsSuccess() {
		return res, errors.New("get sts cert abnormal：" + res.String())
	}
	// 3. 响应结果
	return res, nil
}
